// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.util.io;

import java.nio.ByteBuffer;
import java.util.concurrent.ConcurrentLinkedDeque;
import zombie.core.utils.Bits;
import zombie.debug.DebugLog;

public final class BitHeader {
    private static final ConcurrentLinkedDeque<BitHeader.BitHeaderByte> pool_byte = new ConcurrentLinkedDeque();
    private static final ConcurrentLinkedDeque<BitHeader.BitHeaderShort> pool_short = new ConcurrentLinkedDeque();
    private static final ConcurrentLinkedDeque<BitHeader.BitHeaderInt> pool_int = new ConcurrentLinkedDeque();
    private static final ConcurrentLinkedDeque<BitHeader.BitHeaderLong> pool_long = new ConcurrentLinkedDeque();
    public static boolean DEBUG = true;

    private static BitHeader.BitHeaderBase getHeader(BitHeader.HeaderSize headerSize, ByteBuffer byteBuffer, boolean _boolean) {
        if (headerSize == BitHeader.HeaderSize.Byte) {
            BitHeader.BitHeaderByte bitHeaderByte = (BitHeader.BitHeaderByte)pool_byte.poll();
            if (bitHeaderByte == null) {
                bitHeaderByte = new BitHeader.BitHeaderByte();
            }

            bitHeaderByte.setBuffer(byteBuffer);
            bitHeaderByte.setWrite(_boolean);
            return bitHeaderByte;
        } else if (headerSize == BitHeader.HeaderSize.Short) {
            BitHeader.BitHeaderShort bitHeaderShort = (BitHeader.BitHeaderShort)pool_short.poll();
            if (bitHeaderShort == null) {
                bitHeaderShort = new BitHeader.BitHeaderShort();
            }

            bitHeaderShort.setBuffer(byteBuffer);
            bitHeaderShort.setWrite(_boolean);
            return bitHeaderShort;
        } else if (headerSize == BitHeader.HeaderSize.Integer) {
            BitHeader.BitHeaderInt bitHeaderInt = (BitHeader.BitHeaderInt)pool_int.poll();
            if (bitHeaderInt == null) {
                bitHeaderInt = new BitHeader.BitHeaderInt();
            }

            bitHeaderInt.setBuffer(byteBuffer);
            bitHeaderInt.setWrite(_boolean);
            return bitHeaderInt;
        } else if (headerSize == BitHeader.HeaderSize.Long) {
            BitHeader.BitHeaderLong bitHeaderLong = (BitHeader.BitHeaderLong)pool_long.poll();
            if (bitHeaderLong == null) {
                bitHeaderLong = new BitHeader.BitHeaderLong();
            }

            bitHeaderLong.setBuffer(byteBuffer);
            bitHeaderLong.setWrite(_boolean);
            return bitHeaderLong;
        } else {
            return null;
        }
    }

    private BitHeader() {
    }

    public static void debug_print() {
        if (DEBUG) {
            DebugLog.log("*********************************************");
            DebugLog.log("ByteHeader = " + pool_byte.size());
            DebugLog.log("ShortHeader = " + pool_short.size());
            DebugLog.log("IntHeader = " + pool_int.size());
            DebugLog.log("LongHeader = " + pool_long.size());
        }
    }

    public static BitHeaderWrite allocWrite(BitHeader.HeaderSize size, ByteBuffer buffer) {
        return allocWrite(size, buffer, false);
    }

    public static BitHeaderWrite allocWrite(BitHeader.HeaderSize size, ByteBuffer buffer, boolean allocOnly) {
        BitHeader.BitHeaderBase bitHeaderBase = getHeader(size, buffer, true);
        if (!allocOnly) {
            bitHeaderBase.create();
        }

        return bitHeaderBase;
    }

    public static BitHeaderRead allocRead(BitHeader.HeaderSize size, ByteBuffer buffer) {
        return allocRead(size, buffer, false);
    }

    public static BitHeaderRead allocRead(BitHeader.HeaderSize size, ByteBuffer buffer, boolean allocOnly) {
        BitHeader.BitHeaderBase bitHeaderBase = getHeader(size, buffer, false);
        if (!allocOnly) {
            bitHeaderBase.read();
        }

        return bitHeaderBase;
    }

    public abstract static class BitHeaderBase implements BitHeaderRead, BitHeaderWrite {
        protected boolean isWrite;
        protected ByteBuffer buffer;
        protected int start_pos = -1;

        protected void setBuffer(ByteBuffer byteBuffer) {
            this.buffer = byteBuffer;
        }

        protected void setWrite(boolean _boolean) {
            this.isWrite = _boolean;
        }

        @Override
        public int getStartPosition() {
            return this.start_pos;
        }

        protected void reset() {
            this.buffer = null;
            this.isWrite = false;
            this.start_pos = -1;
            this.reset_header();
        }

        @Override
        public abstract int getLen();

        @Override
        public abstract void release();

        protected abstract void reset_header();

        protected abstract void write_header();

        protected abstract void read_header();

        protected abstract void addflags_header(int var1);

        protected abstract void addflags_header(long var1);

        protected abstract boolean hasflags_header(int var1);

        protected abstract boolean hasflags_header(long var1);

        protected abstract boolean equals_header(int var1);

        protected abstract boolean equals_header(long var1);

        @Override
        public void create() {
            if (this.isWrite) {
                this.start_pos = this.buffer.position();
                this.reset_header();
                this.write_header();
            } else {
                throw new RuntimeException("BitHeader -> Cannot write to a non write Header.");
            }
        }

        @Override
        public void write() {
            if (this.isWrite) {
                int _int = this.buffer.position();
                this.buffer.position(this.start_pos);
                this.write_header();
                this.buffer.position(_int);
            } else {
                throw new RuntimeException("BitHeader -> Cannot write to a non write Header.");
            }
        }

        @Override
        public void read() {
            if (!this.isWrite) {
                this.start_pos = this.buffer.position();
                this.read_header();
            } else {
                throw new RuntimeException("BitHeader -> Cannot read from a non read Header.");
            }
        }

        @Override
        public void addFlags(int flags) {
            if (this.isWrite) {
                this.addflags_header(flags);
            } else {
                throw new RuntimeException("BitHeader -> Cannot set bits on a non write Header.");
            }
        }

        @Override
        public void addFlags(long flags) {
            if (this.isWrite) {
                this.addflags_header(flags);
            } else {
                throw new RuntimeException("BitHeader -> Cannot set bits on a non write Header.");
            }
        }

        @Override
        public boolean hasFlags(int flags) {
            return this.hasflags_header(flags);
        }

        @Override
        public boolean hasFlags(long flags) {
            return this.hasflags_header(flags);
        }

        @Override
        public boolean equals(int flags) {
            return this.equals_header(flags);
        }

        @Override
        public boolean equals(long flags) {
            return this.equals_header(flags);
        }
    }

    public static class BitHeaderByte extends BitHeader.BitHeaderBase {
        private ConcurrentLinkedDeque<BitHeader.BitHeaderByte> pool;
        private byte header;

        private BitHeaderByte() {
        }

        @Override
        public void release() {
            this.reset();
            BitHeader.pool_byte.offer(this);
        }

        @Override
        public int getLen() {
            return Bits.getLen(this.header);
        }

        @Override
        protected void reset_header() {
            this.header = 0;
        }

        @Override
        protected void write_header() {
            this.buffer.put(this.header);
        }

        @Override
        protected void read_header() {
            this.header = this.buffer.get();
        }

        @Override
        protected void addflags_header(int _int) {
            this.header = Bits.addFlags(this.header, _int);
        }

        @Override
        protected void addflags_header(long _long) {
            this.header = Bits.addFlags(this.header, _long);
        }

        @Override
        protected boolean hasflags_header(int _int) {
            return Bits.hasFlags(this.header, _int);
        }

        @Override
        protected boolean hasflags_header(long _long) {
            return Bits.hasFlags(this.header, _long);
        }

        @Override
        protected boolean equals_header(int _int) {
            return this.header == _int;
        }

        @Override
        protected boolean equals_header(long _long) {
            return (long)this.header == _long;
        }
    }

    public static class BitHeaderInt extends BitHeader.BitHeaderBase {
        private ConcurrentLinkedDeque<BitHeader.BitHeaderInt> pool;
        private int header;

        private BitHeaderInt() {
        }

        @Override
        public void release() {
            this.reset();
            BitHeader.pool_int.offer(this);
        }

        @Override
        public int getLen() {
            return Bits.getLen(this.header);
        }

        @Override
        protected void reset_header() {
            this.header = 0;
        }

        @Override
        protected void write_header() {
            this.buffer.putInt(this.header);
        }

        @Override
        protected void read_header() {
            this.header = this.buffer.getInt();
        }

        @Override
        protected void addflags_header(int _int) {
            this.header = Bits.addFlags(this.header, _int);
        }

        @Override
        protected void addflags_header(long _long) {
            this.header = Bits.addFlags(this.header, _long);
        }

        @Override
        protected boolean hasflags_header(int _int) {
            return Bits.hasFlags(this.header, _int);
        }

        @Override
        protected boolean hasflags_header(long _long) {
            return Bits.hasFlags(this.header, _long);
        }

        @Override
        protected boolean equals_header(int _int) {
            return this.header == _int;
        }

        @Override
        protected boolean equals_header(long _long) {
            return (long)this.header == _long;
        }
    }

    public static class BitHeaderLong extends BitHeader.BitHeaderBase {
        private ConcurrentLinkedDeque<BitHeader.BitHeaderLong> pool;
        private long header;

        private BitHeaderLong() {
        }

        @Override
        public void release() {
            this.reset();
            BitHeader.pool_long.offer(this);
        }

        @Override
        public int getLen() {
            return Bits.getLen(this.header);
        }

        @Override
        protected void reset_header() {
            this.header = 0L;
        }

        @Override
        protected void write_header() {
            this.buffer.putLong(this.header);
        }

        @Override
        protected void read_header() {
            this.header = this.buffer.getLong();
        }

        @Override
        protected void addflags_header(int _int) {
            this.header = Bits.addFlags(this.header, _int);
        }

        @Override
        protected void addflags_header(long _long) {
            this.header = Bits.addFlags(this.header, _long);
        }

        @Override
        protected boolean hasflags_header(int _int) {
            return Bits.hasFlags(this.header, _int);
        }

        @Override
        protected boolean hasflags_header(long _long) {
            return Bits.hasFlags(this.header, _long);
        }

        @Override
        protected boolean equals_header(int _int) {
            return this.header == (long)_int;
        }

        @Override
        protected boolean equals_header(long _long) {
            return this.header == _long;
        }
    }

    public static class BitHeaderShort extends BitHeader.BitHeaderBase {
        private ConcurrentLinkedDeque<BitHeader.BitHeaderShort> pool;
        private short header;

        private BitHeaderShort() {
        }

        @Override
        public void release() {
            this.reset();
            BitHeader.pool_short.offer(this);
        }

        @Override
        public int getLen() {
            return Bits.getLen(this.header);
        }

        @Override
        protected void reset_header() {
            this.header = 0;
        }

        @Override
        protected void write_header() {
            this.buffer.putShort(this.header);
        }

        @Override
        protected void read_header() {
            this.header = this.buffer.getShort();
        }

        @Override
        protected void addflags_header(int _int) {
            this.header = Bits.addFlags(this.header, _int);
        }

        @Override
        protected void addflags_header(long _long) {
            this.header = Bits.addFlags(this.header, _long);
        }

        @Override
        protected boolean hasflags_header(int _int) {
            return Bits.hasFlags(this.header, _int);
        }

        @Override
        protected boolean hasflags_header(long _long) {
            return Bits.hasFlags(this.header, _long);
        }

        @Override
        protected boolean equals_header(int _int) {
            return this.header == _int;
        }

        @Override
        protected boolean equals_header(long _long) {
            return (long)this.header == _long;
        }
    }

    public static enum HeaderSize {
        Byte,
        Short,
        Integer,
        Long;
    }
}
